package com.wuzheng.wisgo.sanitation.cloud.service.roadandstatus.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wuzheng.wisgo.sanitation.cloud.enums.RedisEnum;
import com.wuzheng.wisgo.sanitation.cloud.model.roadandstatus.LngLatAndErrorNumDto;
import com.wuzheng.wisgo.sanitation.cloud.model.roadandstatus.ReceviceLngLatDto;
import com.wuzheng.wisgo.sanitation.cloud.model.roadandstatus.RoadInfoDto;
import com.wuzheng.wisgo.sanitation.cloud.model.roadandstatus.TrashLngLatDto;
import com.wuzheng.wisgo.sanitation.cloud.paraandgetutil.Exceptions;
import com.wuzheng.wisgo.sanitation.cloud.paraandgetutil.ParameterRetUtils;
import com.wuzheng.wisgo.sanitation.cloud.paraandgetutil.PointInMapArithmeticUtils;
import com.wuzheng.wisgo.sanitation.cloud.paraandgetutil.VehicleException;
import com.wuzheng.wisgo.sanitation.cloud.repository.entity.jobcompletion.BaJobCompletion;
import com.wuzheng.wisgo.sanitation.cloud.repository.entity.jobcompletion.BaJobCompletionRoadItem;
import com.wuzheng.wisgo.sanitation.cloud.repository.entity.jobcompletion.JobCompletionTrashItem;
import com.wuzheng.wisgo.sanitation.cloud.repository.mapper.jobcompletion.BaJobCompletionMapper;
import com.wuzheng.wisgo.sanitation.cloud.repository.mapper.roadandstate.RouteStateMapper;
import com.wuzheng.wisgo.sanitation.cloud.service.jobcompletion.BaJobCompletionRoadItemService;
import com.wuzheng.wisgo.sanitation.cloud.service.jobcompletion.BaJobCompletionService;
import com.wuzheng.wisgo.sanitation.cloud.service.jobcompletion.JobCompletionTrashItemService;
import com.wuzheng.wisgo.sanitation.cloud.service.roadandstatus.RouteStateService;
import com.wuzheng.wisgo.sanitation.framework.util.RedisUtils;
import com.wuzheng.wisgo.sanitation.framework.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/*
 * @Description: 路/垃圾桶是否作业
 * @Author: sunpeng
 * @Date: 2019/12/18
 **/
@Service
public class RouteStateServiceImpl implements RouteStateService {

    private final static Logger logger = LoggerFactory.getLogger(RouteStateServiceImpl.class);

    @Autowired
    private RouteStateMapper routeStateMapper;

    @Autowired
    private BaJobCompletionService baJobCompletionService;

    @Autowired
    private JobCompletionTrashItemService jobCompletionTrashItemService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private BaJobCompletionRoadItemService baJobCompletionRoadItemService;
    @Autowired
    private BaJobCompletionMapper baJobCompletionMapper;

    /*
     * @Description: 垃圾桶是否清运判断
     * @Author: sunpeng
     * @Date: 2019/12/20
     **/
    @Override
    public void trashCanToStatus(ReceviceLngLatDto receviceLngLatDto) throws VehicleException {
        //接受参数校验
        this.check(receviceLngLatDto);
        //通过道路作业关联关系表-找到与之对应的垃圾桶关系
        //找到垃圾桶的经纬度位置
        List<TrashLngLatDto> lngLatList = routeStateMapper.selectTranshFromJobPlan(receviceLngLatDto.getVehVin());
        if (lngLatList.size() > 0) {
            for (TrashLngLatDto trashLngLatDto : lngLatList) {
                //计算GPS定位的经纬度与垃圾桶的经纬度关系
                //数据初始化，初始的是垃圾桶原始的经纬度，跟GPS误差半径
                PointInMapArithmeticUtils pointInMapArithmeticUtils = new PointInMapArithmeticUtils(trashLngLatDto.getTrashLong(), trashLngLatDto.getTrashLat(), trashLngLatDto.getErrorThreshold());
                boolean inArea = pointInMapArithmeticUtils.isInArea(receviceLngLatDto.gettLongitude(), receviceLngLatDto.gettLatitude());
                //inArea=true说明在垃圾桶范围内
                if (inArea) {
                    List<JobCompletionTrashItem> jobCompletionTrash = routeStateMapper.selectBaJobCompletionTrashItem(trashLngLatDto.getTrashLong(), trashLngLatDto.getTrashLat());
                    //如果在转运垃圾桶停留明细表中存在数据
                    //当前报文上传时间-get(0)最小时间
                    long startNowTime = receviceLngLatDto.getRecCollectionTime().getTime();
                    long endNowTime = new Date().getTime();
                    //插入作业完成明细表：无论是否符合作业标准，都要插入数据
                    JobCompletionTrashItem jobCompletionTrashItem = new JobCompletionTrashItem();
                    jobCompletionTrashItem.setId(UUID.randomUUID().toString());
                    jobCompletionTrashItem.setTrashId(trashLngLatDto.getTrashId());
                    jobCompletionTrashItem.settLong(receviceLngLatDto.gettLongitude());
                    jobCompletionTrashItem.settLng(receviceLngLatDto.gettLatitude());
                    jobCompletionTrashItem.setTrashLong(trashLngLatDto.getTrashLong());
                    jobCompletionTrashItem.setTrashLng(trashLngLatDto.getTrashLat());
                    jobCompletionTrashItem.setVehVin(receviceLngLatDto.getVehVin());
                    jobCompletionTrashItem.setRecCollectionTime(receviceLngLatDto.getRecCollectionTime());
                    jobCompletionTrashItem.setCreateTime(new Date());
                    if (jobCompletionTrash.size() == 0) {
                        jobCompletionTrashItemService.insert(jobCompletionTrashItem);
                    } else {
                        endNowTime = jobCompletionTrash.get(0).getRecCollectionTime().getTime();
                        jobCompletionTrashItem.setId(jobCompletionTrash.get(0).getId());
                        jobCompletionTrashItemService.updateById(jobCompletionTrashItem);
                    }

                    //当前停留分钟
                    long stopTime = (startNowTime - endNowTime) / (1000 * 60);
                    long time_pd = 0L;
                    try {
                        String propertiesParameter = ParameterRetUtils.getPropertiesParameter("trash.time");
                        time_pd = Long.valueOf(propertiesParameter);
                    } catch (IOException e) {
                        e.printStackTrace();

                    }
                    if (stopTime - time_pd >= 0) {
                        //插入作业完成情况表
                        BaJobCompletion baJobCompletion = new BaJobCompletion();
                        baJobCompletion.setId(UUID.randomUUID().toString());
                        baJobCompletion.setCustomerId("wz");
                        baJobCompletion.setStopTime(String.valueOf(stopTime));
                        baJobCompletion.setVehVinCode(receviceLngLatDto.getVehVin());
                        baJobCompletion.setRoadTrashId(trashLngLatDto.getTrashId());
                        baJobCompletion.setDataCollectionTime(receviceLngLatDto.getRecCollectionTime());
                        baJobCompletion.setMapLong(receviceLngLatDto.gettLongitude());
                        baJobCompletion.setMapLng(receviceLngLatDto.gettLatitude());
                        baJobCompletion.setGpsLong(receviceLngLatDto.getLongitude());
                        baJobCompletion.setGpsLng(receviceLngLatDto.getLatitude());
                        baJobCompletion.setCreator("sys");
                        baJobCompletion.setCreateTime(new Date());
                        baJobCompletionService.insert(baJobCompletion);
                    }

                }
            }

        }


    }

    /*
     * @Description: 垃圾桶是否清运判断方法，所接收的数据校验
     * @Author: sunpeng
     * @Date: 2019/12/20
     **/
    private void check(ReceviceLngLatDto receviceLngLatDto) throws VehicleException {
        if (StringUtils.isEmpty(receviceLngLatDto.getVehVin())) {
            throw Exceptions.VehicleException("Vin码不能同时为空");
        }
        if (receviceLngLatDto.getLongitude() == null) {
            throw Exceptions.VehicleException("原始精度不能为空");
        }
        if (receviceLngLatDto.getLatitude() == null) {
            throw Exceptions.VehicleException("原始维度不能为空");
        }
        if (receviceLngLatDto.gettLongitude() == null) {
            throw Exceptions.VehicleException("转义后精度不能为空");
        }
        if (receviceLngLatDto.gettLatitude() == null) {
            throw Exceptions.VehicleException("转义后维度不能为空");
        }
    }

    /*
     * @Description: 判断当前道路是否作业
     * @Param: [vehVin,tLong, tLat] 转义后的经纬度
     * @Author: sunpeng
     * @Date: 2019/12/20
     **/
    @Override
    public void roadJudgeStatus(ReceviceLngLatDto receviceLngLatDto) throws VehicleException {
        this.check(receviceLngLatDto);
        //1.根据vin码，找到车辆与道路的对应关系
        List<RoadInfoDto> roadInfoDtos = routeStateMapper.selectRoadFromVehVin(receviceLngLatDto.getVehVin());
        List<LngLatAndErrorNumDto> roadLongLats = new ArrayList<>();//存放所有道路的经纬度点
        Map<String, List<LngLatAndErrorNumDto>> map = new HashMap<>();
        if (roadInfoDtos.size() > 0) {
            for (RoadInfoDto roadInfoDto : roadInfoDtos) {
                if (roadInfoDto.getGpsFeatures().length > 0) {
                    for (int i = 0; i < roadInfoDto.getGpsFeatures().length; i++) {

                        String[] split = roadInfoDto.getGpsFeatures()[i].split(";");
                        if (split.length > 0) {
                            List<String> list = Arrays.asList(split);
                            if (list.size() > 0) {
                                for (int j = 0; j < list.size(); j++) {
                                    String[] longSpitLnt = list.get(j).split(",");
                                    if (longSpitLnt.length == 2) {
                                        LngLatAndErrorNumDto lngLatAndErrorNumDto = new LngLatAndErrorNumDto();
                                        lngLatAndErrorNumDto.settLongitude(Double.valueOf(longSpitLnt[0]));
                                        lngLatAndErrorNumDto.settLatitude(Double.valueOf(longSpitLnt[1]));
                                        lngLatAndErrorNumDto.setGpsOffset(roadInfoDto.getGpsOffset());
                                        roadLongLats.add(lngLatAndErrorNumDto);
                                    }
                                }
                            }
                        } else {
                            throw Exceptions.VehicleException("道路经纬度点为空，id=" + roadInfoDto.getRoadId());
                        }
                    }
                }
                map.put(roadInfoDto.getRoadId(), roadLongLats);
            }
        }
        //2.每次判断当前经纬度点是否正在作业的时候，先去查看redis中是否已经判断过当前点
        //注意已经作业完成的数据，存redis，并设置过期时间，暂时设置5分钟
        String key = receviceLngLatDto.getLongitude().toString() + "_" + receviceLngLatDto.getLatitude().toString() + "_" + RedisEnum.WORK.getTypeId();
        Object o = redisUtils.get(key);
        if (o != null) {
            //如果存在数据，说明当前点已经判断过工作状态
            BaJobCompletion jobCompletion=new BaJobCompletion();
            try{
                 jobCompletion = JSONObject.parseObject(o.toString(), BaJobCompletion.class);
            } catch (Exception e) {
                //无论任何异常，都应记录下来，并且不影响下次循环判断
                e.printStackTrace();
                logger.error("缓存数据获取异常:"+e.getMessage());
            }
            BaJobCompletion baJobCompletion = new BaJobCompletion();
            baJobCompletion.setId(UUID.randomUUID().toString());
            baJobCompletion.setCustomerId("wz");
            baJobCompletion.setVehVinCode(receviceLngLatDto.getVehVin());
            baJobCompletion.setDataCollectionTime(receviceLngLatDto.getRecCollectionTime());
            baJobCompletion.setMapLong(receviceLngLatDto.gettLongitude());
            baJobCompletion.setMapLng(receviceLngLatDto.gettLatitude());
            baJobCompletion.setGpsLong(receviceLngLatDto.getLongitude());
            baJobCompletion.setGpsLng(receviceLngLatDto.getLatitude());
            baJobCompletion.setRoadTrashId(jobCompletion.getRoadTrashId());
            baJobCompletion.setCreator("sys");
            baJobCompletion.setCreateTime(new Date());
        } else {
            for (String roadIdKey : map.keySet()) {
                List<LngLatAndErrorNumDto> gps = map.get(roadIdKey);
                for (LngLatAndErrorNumDto lngLatAndErrorNumDto : gps) {
                    //初始化数据
                    PointInMapArithmeticUtils pointInMapArithmeticUtils =
                            new PointInMapArithmeticUtils(lngLatAndErrorNumDto.gettLongitude(), lngLatAndErrorNumDto.gettLatitude(), Double.valueOf(lngLatAndErrorNumDto.getGpsOffset()));
                    boolean inArea = pointInMapArithmeticUtils.isInArea(receviceLngLatDto.gettLongitude(), receviceLngLatDto.gettLatitude());
                    if (inArea) {
                        try {
                            //封装插入数据
                            BaJobCompletion baJobCompletion = new BaJobCompletion();
                            baJobCompletion.setId(UUID.randomUUID().toString());
                            baJobCompletion.setCustomerId("wz");
                            baJobCompletion.setVehVinCode(receviceLngLatDto.getVehVin());
                            baJobCompletion.setDataCollectionTime(receviceLngLatDto.getRecCollectionTime());
                            baJobCompletion.setMapLong(receviceLngLatDto.gettLongitude());
                            baJobCompletion.setMapLng(receviceLngLatDto.gettLatitude());
                            baJobCompletion.setGpsLong(receviceLngLatDto.getLongitude());
                            baJobCompletion.setGpsLng(receviceLngLatDto.getLatitude());
                            baJobCompletion.setRoadTrashId(roadIdKey);
                            baJobCompletion.setCreator("sys");
                            baJobCompletion.setCreateTime(new Date());
                            baJobCompletion.setWorkStatus("work");
                            baJobCompletionService.insert(baJobCompletion);
                            redisUtils.set(key, JSONObject.toJSON(baJobCompletion).toString(), 5, TimeUnit.MINUTES);


                            BaJobCompletionRoadItem baJobCompletionRoadItem = new BaJobCompletionRoadItem();
                            baJobCompletionRoadItem.setId(UUID.randomUUID().toString());
                            baJobCompletionRoadItem.setRoadId(roadIdKey);
                            baJobCompletionRoadItem.setRoadLong(lngLatAndErrorNumDto.gettLongitude());
                            baJobCompletionRoadItem.setRoadLng(lngLatAndErrorNumDto.gettLatitude());
                            baJobCompletionRoadItem.setSysTime(new Date());
                            baJobCompletionRoadItem.setVehVin(receviceLngLatDto.getVehVin());
                            baJobCompletionRoadItemService.insert(baJobCompletionRoadItem);
                        } catch (Exception e) {
                            //无论任何异常，都应记录下来，并且不影响下次循环判断
                            e.printStackTrace();
                            logger.error("判断道路是否作业异常:"+e.getMessage());
                            continue;
                        }
                    }


                }

            }
        }
    }


}
